/*
 * Copyright 2016 atnoce.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.atnoce.view;

import com.atnoce.Start;
import com.atnoce.core.SecurityController;
import com.atnoce.db.ConfigDao;
import com.atnoce.db.PasswordDao;
import com.atnoce.net.BasicNetService;
import com.atnoce.pojo.OnepassConfig;
import com.atnoce.pojo.PasswordItem;
import com.atnoce.util.Cache;
import com.atnoce.util.CommonUtil;
import com.atnoce.util.InitContext;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javafx.application.Platform;

import org.apache.commons.lang.StringUtils;


import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.util.Pair;

public class PreferencesLayoutController {

	private Start start;
	private Stage preferencesDialogStage;
	private final ConfigDao cd=new ConfigDao();
        private final PasswordDao pd=new PasswordDao();
	public void setStart(Start start){
		this.start=start;
	}
	public void setPreferencesDialogStage(Stage preferencesDialogStage){
		this.preferencesDialogStage=preferencesDialogStage;
	}

	//---安全配置
        @FXML
        private ChoiceBox<Integer> jiaMiNum;
        @FXML
        private ImageView helpImg;
	@FXML
	private Button savePassGenerConfigBtn;
        @FXML
        private Button changeMainPassBtn;
	//--常规配置
	@FXML
	private CheckBox startAutoUpdate;
	@FXML
	private CheckBox minSysTuoPan;
	@FXML
	private CheckBox closeMinWindowNoClose;
	@FXML
	private CheckBox autoClearPanel;
	@FXML
	private ChoiceBox<String> autoClearPanelTime;
	@FXML
	private CheckBox minningLock;
	@FXML
	private CheckBox kongXianLock;
	@FXML
	private ChoiceBox<String> kongXianLockTime;
	@FXML
	private Button saveChangGuiBtn;

	@FXML
	private TabPane tablePanel;
        
        //云服务
        @FXML
        private Label topLabel;
        @FXML
        private TextField coludAccountInput;
        @FXML
        private Button regBtn;
        @FXML
        private HBox regHboxPanel;
        
	@FXML
	private void initialize(){
		tablePanel.getSelectionModel().selectedItemProperty().addListener(
				(observable,oldValue,newValue)->{
			String text = newValue.getText();
			if(StringUtils.equals("安全", text)){
                            
                        }else if(StringUtils.equals("常规", text)){
                            initChangGuiConfig(newValue);
                        }else if(StringUtils.equals("云服务", text)){
                            if(Boolean.valueOf(Cache.proMap.get("actioncloud"))){
                                
                                try {
                                    topLabel.setText("已绑定账号:"+SecurityController.getSecurityInstence().decryptColudAccount(Cache.proMap.get("coludaccount")));
                                } catch (Exception ex) {
                                }
                                topLabel.setTextFill(Color.web("#008000"));
                                regHboxPanel.setDisable(true);
                                regHboxPanel.setVisible(false);
                            }
                        }
				
		});
		savePassGenerConfigBtn.setOnAction(e->savePassGenerConfigHandler());
		saveChangGuiBtn.setOnAction(e->saveChangGuiBtnHandler());
		//tablePanel.getSelectionModel().selectLast();
		initChangGuiConfig(tablePanel.getSelectionModel().getSelectedItem());
                
                regBtn.setOnAction(e->regColud());
                
                changeMainPassBtn.setOnAction(e->changeMainPassBtnHandler());
                coludAccountInput.textProperty().addListener((observable,oldValue,newValue)->{
                    regBtn.setDisable(newValue.trim().isEmpty());
                });
                
	}
        private void changeMainPassBtnHandler(){
            Dialog<Pair<String,String>> dialog=new Dialog<>();
            dialog.setTitle("修改主密码");
            dialog.setHeaderText("正在修改主密码");
            dialog.setGraphic(new ImageView(this.getClass().getResource("image/1.jpg").toString()));
            
            ButtonType changeBtnType=new ButtonType("修改",ButtonData.OK_DONE);
            dialog.getDialogPane().getButtonTypes().addAll(changeBtnType,ButtonType.CANCEL);
            
            GridPane grid=new GridPane();
            grid.setHgap(10);
            grid.setVgap(10);
            grid.setPadding(new Insets(20,150,10,10));
            
            PasswordField oldPass=new PasswordField();
            oldPass.setPromptText("输入旧密码");
            PasswordField newPass=new PasswordField();
            newPass.setPromptText("输入新密码");
            
            grid.add(new Label("旧密码:"), 0, 0);
            grid.add(oldPass, 1, 0);
            grid.add(new Label("新密码:"), 0, 1);
            grid.add(newPass, 1, 1);
            
            Node lookupButton = dialog.getDialogPane().lookupButton(changeBtnType);
            lookupButton.setDisable(true);
            
            oldPass.textProperty().addListener((observable,oldValue,newValue)->{
                lookupButton.setDisable(newValue.trim().isEmpty());
            });
            
            dialog.getDialogPane().setContent(grid);
            
            Platform.runLater(()->oldPass.requestFocus());
            
            dialog.setResultConverter(dialogButton->{
                if(dialogButton==changeBtnType){
                    return new Pair<>(oldPass.getText(),newPass.getText());
                }
                return null;
            });
            
            Optional<Pair<String, String>> result = dialog.showAndWait();
            result.ifPresent(consumer->{
                String oldp=consumer.getKey();
                String newp=consumer.getValue();
                Alert alert;
                
                if(StringUtils.isBlank(newp)||StringUtils.isBlank(oldp)){
                    alert=new Alert(AlertType.ERROR);
                    alert.setHeaderText("修改失败");
                    alert.setContentText("新密码和旧密码都不能为空");
                    return;
                }else if(StringUtils.equals(oldp, newp)){
                    alert=new Alert(AlertType.ERROR);
                    alert.setHeaderText("修改失败");
                    alert.setContentText("新密码和旧密码相同");
                    alert.showAndWait();
                    return;
                }else if(!SecurityController.getSecurityInstence().checkMainPass(oldp)){
                    alert=new Alert(AlertType.ERROR);
                    alert.setHeaderText("修改失败");
                    alert.setContentText("旧密码输入错误");
                    alert.showAndWait();
                    return;
                }
                String newMainPass=SecurityController.getSecurityInstence().getKey(newp);
                String oldMainPass=Cache.key;
                try {
                    List<PasswordItem> list = pd.getAllPasswordItem();
                    //更新主密码
                    if(cd.updateMainPass(SecurityController.getSecurityInstence().encryptionMain(newp))){
                        if(!list.isEmpty()){
                            for(PasswordItem pi:list){
                                try {
                                    //首先解密
                                    pi.setAccount(SecurityController.getSecurityInstence().AESdecrypt(pi.getAccount(), oldMainPass));
                                    pi.setPasswordStr(SecurityController.getSecurityInstence().AESdecrypt(pi.getPasswordStr(), oldMainPass));
                                    //用新密码加密
                                    pi.setAccount(SecurityController.getSecurityInstence().AESencrypt(pi.getAccount(), newMainPass));
                                    pi.setPasswordStr(SecurityController.getSecurityInstence().AESencrypt(pi.getPasswordStr(), newMainPass));
                                } catch (Exception ex) {
                                }
                            //保存
                            pd.updatePasswordItemFromId(pi);
                            }
                            Cache.oc.setMainPass(newMainPass);
                        }
                    }
                    if(Boolean.valueOf(Cache.proMap.get("actioncloud"))){//已经激活云服务
                        //更新配置信息中的云账号
                        String coludaccount=SecurityController.getSecurityInstence().AESdecrypt(Cache.proMap.get("coludaccount"), oldMainPass);
                        coludaccount=SecurityController.getSecurityInstence().AESencrypt(coludaccount, newMainPass);

                        //更新配置文件
                        InitContext.updateProperties("coludaccount", coludaccount);
                    }
                    
                    
                    alert=new Alert(Alert.AlertType.INFORMATION);
                    alert.setHeaderText("密码修改成功!");
                    alert.setContentText("主密码修改后请使用新密码重新登录系统!");
                    alert.showAndWait();
                    preferencesDialogStage.close();
                    start.initLoginLayout(null);
                } catch (SQLException ex) {
                    alert=new Alert(Alert.AlertType.ERROR);
                    alert.setHeaderText("修改失败");
                    alert.setContentText("修改主密码时发生系统错误!");
                    alert.showAndWait();
                } catch (IOException ex) {
                     alert=new Alert(Alert.AlertType.ERROR);
                    alert.setHeaderText("修改失败");
                    alert.setContentText("修改主密码时发生系统错误!读取数据文件发生异常");
                    alert.showAndWait();
                }catch(ClassNotFoundException ex){
                    alert=new Alert(Alert.AlertType.ERROR);
                    alert.setHeaderText("修改失败");
                    alert.setContentText("找不到数据库驱动");
                    alert.showAndWait();
                } catch (Exception ex) {
                }
            });
        }
	//保存常规设置
	private void saveChangGuiBtnHandler(){
		Boolean start = startAutoUpdate.selectedProperty().getValue();
		Boolean tuopan = minSysTuoPan.selectedProperty().getValue();
		Boolean close = closeMinWindowNoClose.selectedProperty().getValue();
		Boolean clear = autoClearPanel.selectedProperty().getValue();
		String autoClearTime = autoClearPanelTime.getSelectionModel().getSelectedItem();
		Boolean min = minningLock.selectedProperty().getValue();
		Boolean kongxian = kongXianLock.selectedProperty().getValue();
		String kongxiantime = kongXianLockTime.getSelectionModel().getSelectedItem();

		OnepassConfig oc=new OnepassConfig();
		oc.setStartAutoUpdate(String.valueOf(start));
		oc.setMinSysTuoPan(String.valueOf(tuopan));
		oc.setCloseMinWindowNoClose(String.valueOf(close));
		oc.setAutoClearPanel(String.valueOf(clear));
		oc.setAutoClearPanelTime(autoClearTime);
		oc.setMinningLock(String.valueOf(min));
		oc.setKongXianLock(String.valueOf(kongxian));
		oc.setKongXianLockTime(String.valueOf(kongxiantime));
		Alert alert;
		try{
			if(cd.saveChangGuiConfig(oc)){
				alert=new Alert(AlertType.INFORMATION);
				alert.setTitle("成功");
				alert.setHeaderText(null);
				alert.setContentText("配置信息保存成功,新的配置将在下次启动后生效！");
				alert.showAndWait();
			}else{
				alert=new Alert(AlertType.ERROR);
				alert.setTitle("失败");
				alert.setHeaderText(null);
				alert.setContentText("配置信息保存失败");
				alert.showAndWait();
			}
		}catch(SQLException e){
                    alert=new Alert(Alert.AlertType.ERROR);
                    alert.setHeaderText("保存失败");
                    alert.setContentText("数据文件写入配置信息时发生异常！");
                    alert.showAndWait();
		}catch(ClassNotFoundException e){
                    alert=new Alert(Alert.AlertType.ERROR);
                    alert.setHeaderText("保存失败");
                    alert.setContentText("找不到数据库驱动！");
                    alert.showAndWait();
                }
	}
	private void initChangGuiConfig(Tab tab){
            //暂时隐藏未实现的设置项
            autoClearPanelTime.setVisible(false);
            autoClearPanel.setVisible(false);
            minSysTuoPan.setVisible(false);
            closeMinWindowNoClose.setVisible(false);
            minningLock.setVisible(false);
            
		autoClearPanelTime.setItems(FXCollections.observableArrayList("3","5","8","10","12","15","20","30"));
		kongXianLockTime.setItems(FXCollections.observableArrayList("3","5","10","15","20","30"));
		autoClearPanelTime.getSelectionModel().selectFirst();
		kongXianLockTime.getSelectionModel().selectFirst();
		autoClearPanel.setOnAction(e->{
			autoClearPanelTime.setDisable(!autoClearPanel.isSelected());
		});
		kongXianLock.setOnAction(e->{
			kongXianLockTime.setDisable(!kongXianLock.isSelected());
		});
		try{
			OnepassConfig onepassConfig=cd.getOnepassConfig();
			if(onepassConfig!=null){
				if(StringUtils.equals("true", onepassConfig.getStartAutoUpdate())){
					startAutoUpdate.selectedProperty().setValue(true);
				}
				if(StringUtils.equals("true", onepassConfig.getMinSysTuoPan())){
					minSysTuoPan.selectedProperty().setValue(true);
				}
				if(StringUtils.equals("true", onepassConfig.getCloseMinWindowNoClose())){
					closeMinWindowNoClose.selectedProperty().setValue(true);
				}
				if(StringUtils.equals("true", onepassConfig.getAutoClearPanel())){
					autoClearPanel.selectedProperty().setValue(true);
					autoClearPanelTime.setDisable(false);
				}
				if(StringUtils.equals("true", onepassConfig.getMinningLock())){
					minningLock.selectedProperty().setValue(true);
				}
				if(StringUtils.equals("true", onepassConfig.getKongXianLock())){
					kongXianLock.selectedProperty().setValue(true);
					kongXianLockTime.setDisable(false);
				}
				if(StringUtils.isNotBlank(onepassConfig.getAutoClearPanelTime())){
					autoClearPanelTime.getSelectionModel().select(onepassConfig.getAutoClearPanelTime());
				}
				if(StringUtils.isNotBlank(onepassConfig.getKongXianLockTime())){
					kongXianLockTime.getSelectionModel().select(onepassConfig.getKongXianLockTime());
				}

			}
		}catch(SQLException e){
                    Alert alert=new Alert(Alert.AlertType.ERROR);
                    alert.setHeaderText("初始话常规配置错误");
                    alert.setContentText("从数据文件读取常规配置信息时发生异常！");
                    alert.showAndWait();
		}catch(ClassNotFoundException e){
                    Alert alert=new Alert(Alert.AlertType.ERROR);
                    alert.setHeaderText("初始话常规配置错误");
                    alert.setContentText("找不到数据库驱动！");
                    alert.showAndWait();
                }
	}
	private void savePassGenerConfigHandler(){
		//Alert alert;
//            TestNet tn=new TestNet();
//            try {
//                tn.testMd5();
//            } catch (IOException ex) {
//            }
		

	}
        private void regColud(){
            String trim = coludAccountInput.getText().trim();
             Alert alert;
            String check=CommonUtil.checkCloudAccount(trim);
            if(StringUtils.isBlank(check)){
                try {
                    Map<String, Object> result = BasicNetService.getInstance().regCheckColudAccount(trim);
                   
                    if((boolean)result.get("flag")){
                        topLabel.setText("已绑定账号:"+trim);
                        topLabel.setTextFill(Color.web("#008000"));
                        regHboxPanel.setDisable(true);
                        
                        alert=new Alert(AlertType.INFORMATION);
                        alert.setHeaderText("注册成功!");
                        alert.setContentText("从现在起onepass将会自动同步你的密码库至服务器,在新设备上登录该账号可以将服务器密码库同步至本地.");
                        alert.showAndWait();
                        //更新配置文件信息     
                        InitContext.updateProperties("actioncloud", "true");
                        InitContext.updateProperties("coludaccount", SecurityController.getSecurityInstence().encryptColudAccount(trim));
                        //InitContext.init();//重新读取系统配置
                    }else{
                        alert=new Alert(AlertType.ERROR);
                        alert.setHeaderText("注册失败!");
                        alert.setContentText(new String(((String)result.get("msg")).getBytes(),"utf-8"));
                        alert.showAndWait();
                    }
                } catch (IOException ex) {
                    alert=new Alert(AlertType.ERROR);
                    alert.setHeaderText("网络连接失败!");
                    alert.setContentText(ex.getMessage()+"\n请确认你可以访问onepass官网服务器：http://www.onepass.vip");
                    alert.showAndWait();
                } catch (Exception ex) {
                }
            }else{
                alert=new Alert(AlertType.ERROR);
                alert.setHeaderText("输入有误!");
                alert.setContentText(check);
                alert.showAndWait();
            }
        }
}
